home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
byte0687.arc
/
CLOCKSET.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-11-20
|
36KB
|
1,135 lines
******************
* *
* CLOCKSET.ASM * Set Time of Clock Cartridge
* * <=> PUBLIC DOMAIN 09-SEP-86 <=>
******************
*
*** created: 03-AUG-86 by Tim Hunkler / Solar Powered Software
*
ROM3 equ $FA0000 ; ROM3 select strobe
ROM4 equ $FB0000 ; ROM4 select strobe
READ equ 0 ; control for READ access (A6=0)
WRT equ 64 ; control for WRITE access (A6=1)
*
* --- Function call definitions for GEM/AES calls
*
APPL_INI equ 0 ; Application initialization
APPL_EXI equ 1 ; Application exit
OBJC_DRA equ 2 ; Object draw
FORM_DO equ 3 ; Form: Do
FORM_DIA equ 4 ; Form: Dialog
FORM_ALE equ 5 ; Form: Alert
FORM_CEN equ 6 ; Form: Center
GRAF_MOU equ 7 ; Graphics: Mouse Form
*
* --- Offset definitions for dynamic storage
*
params equ $0000 ; table of array pointers
control equ $0018 ; array of control counts
global equ $0022 ; array of global variables
int_in equ $0040 ; array of integers in
int_out equ $0060 ; array of integers out
addr_in equ $006E ; array of addresses in
addr_out equ $0072 ; array of addresses out
buffer equ $0076 ; buffer to receive clock chip data
ap_id equ $0026 ; application ID, one of the globals
stack equ $0486 ; stack area (grows downward)
xx equ $048A ; temp area to receive x,y,w,h info
sz_stor equ $0492 ; size of dynamic storage needs
* ===============================
* ----- PROGRAM ENTRY POINT -----
* ===============================
x: lea storage(pc),a5 ; load base of dynamic storage
lea stack(a5),sp ; establish a stack
*
* --- release all memory not needed
*
move.l #(storage-x+256+sz_stor),-(sp) ; push num bytes to keep
pea x-256(pc) ; push address of memory to keep
clr.w -(sp) ; push filler
move.w #74,-(sp) ; push function code = memory shrink
trap #1 ; call the system
lea 12(sp),sp ; fix the stack
*
* --- initialize GEM/AES parameter block
*
lea params+24(a5),a6 ; address end of block
lea control(a5),a0 ; first pntr
lea global(a5),a1 ; second pntr
lea int_in(a5),a2 ; third pntr
lea int_out(a5),a3 ; fourth pntr
lea addr_in(a5),a4 ; fifth pntr
lea addr_out(a5),a5 ; sixth pntr
movem.l a0-a5,-(a6) ; fill data block
*
* --- zero some areas in =global=
*
moveq #14,d0 ; loop for 15 words
zgbl: clr.w (a1)+ ; clear entire array
dbf d0,zgbl
*
* --- initialize base and data pointers and start program
*
lea x(pc),a6 ; A6 will be program base register
lea storage(pc),a5 ; A5 will be data storage base register
*
* --- begin regular program code
*
START: bsr _appl_in ; initialize application
bsr _mouse ; change mouse pointer to an arrow
*
* --- read info from the clock cartridge
*
rdcart: lea buffer(a5),a2 ; load addr of buffer to be filled
bsr r_clock ; read time from the clock cartridge
beq.s hwok ; branch if all went ok
*
* --- clock's time was bad or the hardware is not working
*
lea warning(pc),a0 ; address warning message
bsr _alert ; and display the message
*
* --- process dialog menu
*
hwok: bsr format ; format time/date into dialog strings
bsr dialog ; display and process the dialog
*
* --- determine which exit button was used
*
moveq #1,d3 ; outer box = object #1
bsr tstnclr ; was outer box selected?
bne.s rdcart ; yes, then update the time displayed
moveq #12,d3 ; SET = object #12
bsr tstnclr ; was SET button selected?
beq.s if13 ; no, branch
bsr set_clk ; yes, change time
bra.s rdcart
if13: bsr tstnclr ; was button = EXIT?
beq.s rdcart ; no, then update menu
*
* --- exit this program
*
bsr _appl_ex ; notify GEM of application exit
clr.w -(sp) ; function code = exit
trap #1 ; call TOS and never return!
* =====================================
* ===== w_clock : write to clock =====
* =====================================
*
* in: D0.B = data to be written
* D1.W = register address x 2 to be written to
*
* out: A3.L = pointer to clock address latch
* A4.L = pointer to clock chip select
* D1.W = increased by 2
* D0.W = data present prior to write
* cc's : set by D0
*
* changed: A0,D2
*
* This subroutine is used to write data to the clock chip. The data
* to be written is passed in the lower 4 bits of D0 and 2 times the
* clock register to be accessed in passed in D1.
*
w_clock:
lea ROM3,a3 ; LATCH address
lea ROM4,a4 ; CS low strobe
*
* --- form the clock register address
*
wcep: lea 0(a3,d1.w),a0 ; form proper address
*
* --- mask off 4 bit data and align it into bits 12..15
*
moveq #15,d2 ; load mask
and.w d0,d2 ; mask of 4 bit data item
ror.w #4,d2 ; rotate to upper bits
*
* --- latch address, data, and enable writes to the chip
*
move.b WRT(a0,d2.l),d0 ; read old data, latch new data
*
* --- turn chip select on to start the write operation
*
tst.w (a4) ; set chip select low
addq.w #2,d1 ; update register address
*
* --- turn off write enable, turn off chip select, but hold data
*
tst.b READ(a0,d2.l) ; set chip select high
andi.w #$000F,d0 ; mask off 4 bit data and set cond codes
rts
* =====================================
* ===== r_clock : read from clock =====
* =====================================
*
* in: A2.L = address of 16 byte buffer to be filled
*
* out: D0.L = 0 if all OK, else -1
* cc's : set by D0
* (A2) ---> [ flag bits ] leap count, AM/PM, 12/24 hr.
* +1 [ day of week ] 1=Sunday
* +2 [ year x 10 ] 00 = 1980, 01 = 1981, etc.
* +3 [ year x 1 ]
* +4 [ month x 10 ]
* +5 [ month x 1 ]
* [ day x 10 ]
* [ day x 1 ]
* [ hour x 10 ]
* [ hour x 1 ]
* [ minute x 10 ]
* [ minute x 1 ]
* [ second x 10 ]
* [ second x 1 ]
* +14 [ .1 seconds ]
* +15 [ junk byte ]
*
* changed: A0,A4,D1,D2
*
* This subroutine reads all time and date registers from the clock chip
* and fills a 16 byte buffer whose address was passed in A2. As the
* information is read it is added up. Invalid sums typically indicate
* a dead battery or a clock cartridge which is not present and are
* indicated by returning a -1 in register D0 and the condition codes.
* A data changed bit is checked and if the time changed while the read
* operation was in progress the operation is repeated.
*
r_clock:
lea ROM4,a4 ; set pointer for ROM4 strobe
lea ROM3,a0 ; set pntr to register 0
lea 16(a2),a2 ; point to end of buffer to fill
moveq #0,d1 ; set accumulator to zero
*
* --- preload the register address in the latch
*
tst.w (a0)+ ; set register selection to 0
*
* --- loop and read clock registers 0..15
*
moveq #15,d2 ; loop count = 16
fetch: tst.w (a4) ; set chip select on
moveq #15,d0 ; load 4 bit data mask
and.w (a0)+,d0 ; get data, set next addr, select off
move.b d0,-(a2) ; store data in buffer
add.w d0,d1 ; add up all data values
dbf d2,fetch ; and repeat for 16 items
*
* --- retrieve data changed flag (zero indicates no change occurred)
*
tst.w (a4) ; set CS low with register select = 0
moveq #8,d0 ; load mask
and.w (a0),d0 ; get flag, nxt addr = 2, select = off
*
* --- if no clock present we generally accumulate 16 x 15 = 240
*
cmpi.w #125,d1 ; does accumulation indicate bad data?
ble.s nwflg ; no, branch
moveq #-1,d0 ; yes, set error flag
*
* --- test data changed flag and reread the time if necessary
*
nwflg: tst.w d0 ; was data changed (or an error)?
bgt.s r_clock ; yes, then repeat the time reading
rts ; no, exit with cond codes set
* =========================================================
* ===== format: format clock data buffer into dialog =====
* =========================================================
*
* in: A2.L = addr of 16 byte buffer returned by "r_clock"
* out: none
* changed: A0,A1,A2,A3,D0,D1,D2,D3
*
* This subroutine takes the contents of the 16 byte buffer filled
* in by "r_clock" and uses it to format information in the dialog
* menu. The 7 radio buttons which indicate the day of the week are
* set based on the day of the week value of 1..7. The date is
* formatted and the date string is formed. And also the time is
* formatted and the time string is formed.
*
format: lea tree(pc),a3 ; address dialog tree
*
* --- clear radio buttons
*
moveq #6,d2 ; loop for 7 days of the week
moveq #5,d3 ; start with button for SUN
fmtclr: bsr tstnclr ; clear buttons for SUN..SAT
dbra d2,fmtclr ; repeat till done
*
* --- set radio button for day of the week
*
moveq #7,d3 ; load 3 bit mask
and.w (a2)+,d3 ; get day of week, 1..7
addq.w #4,d3 ; convert to object number 5..11
bsr setsel ; set button for SUN..SAT
*
* --- form date string: MM/DD/YY
*
lea s_date+4(pc),a1 ; access date string
move.b (a2)+,(a1) ; copy tens digit of year
addi.b #8,(a1)+ ; modify for 1980 baseline
move.b (a2)+,(a1)+ ; copy ones digit of year
subq.l #6,a1 ; back up to access month
move.b (a2)+,(a1)+ ; move two digits of month
move.b (a2)+,(a1)+
move.b (a2)+,(a1)+ ; move two digits of day-of-month
move.b (a2)+,(a1)+
*
* --- form time string: HH:MM:SS AM
*
moveq #'A',d2 ; preload AM/PM indicator as AM
moveq #15,d0 ; load a mask
and.b (a2)+,d0 ; get tens digit of hour
mulu #10,d0
add.b (a2)+,d0 ; add in ones digit, hours in D0.W
lea s_time+2(pc),a1 ; address minute field
move.b (a2)+,(a1)+ ; move two digits of minutes
move.b (a2)+,(a1)+
move.b (a2)+,(a1)+ ; move two digits of seconds
move.b (a2)+,(a1)+
tst.w d0 ; is it midnight to 1:00 am ?
bne.s ampm ; no, skip ahead
moveq #12,d0 ; yes, change from 00:xx to 12:xx
bra.s AM
ampm: cmpi.w #12,d0 ; does hour indicate PM?
blt.s AM ; for 00:00 to 11:59 no change
beq.s noon ; for 12:00 to 12:59 change flag to 'PM'
subi.w #12,d0 ; for 13:00 to 23:59 reduce by 12 hours
noon: moveq #'P',d2 ; change flag to PM
AM: move.b d2,(a1)+ ; store A or P for AM/PM
subq.l #7,a1 ; point to hours field
divu #10,d0 ; split hours into tens and ones digit
move.b d0,(a1)+ ; store tens digit
swap d0 ; access ones digit
move.b d0,(a1) ; store ones digit
subq.l #1,a1 ; adjust pntr to time string
bsr.s convrt ; convert binary into characters
lea s_date(pc),a1 ; adjust pntr to date string
convrt: moveq #5,d1 ; do 6 digits
cvt: ori.b #'0',(a1)+ ; convert byte into ASCII
dbra d1,cvt
rts
* =======================================================
* ===== set_clk : Set time/date in clock cartridge =====
* =======================================================
*
* in: A3.L = address of dialog tree
* out: none
* changed:
*
* This subroutine uses the time and date present on the dialog
* menu to set the time and date for GEM and TOS. It then converts
* this information into the appropriate fields of the 16 byte table
* filled in by 'r_clock' and uses this table to alter the time and
* date of the MM58274 clock chip.
*
set_clk:
bsr set_time ; set time for TOS and GEM
bne.s tsok ; branch if all went ok
lea badtime(pc),a0 ; address error message
bra _alert ; display alert then return
tsok: lea buffer-1(a5),a2 ; ; access byte prior to buffer
move.b #1,(a2)+ ; install command = %0001
clr.b (a2)+ ; install command = %0000
*
* --- figure out which day of the week is indicated
*
moveq #5,d3 ; select button = SUN
sfdow: bsr tstnclr ; is it selected?
beq.s sfdow ; no, then try next button
subq.w #5,d3 ; convert SUN..SAT into 1..7
move.b d3,(a2)+ ; and store
*
* --- convert the date string into binary nibbles
*
lea s_date+4(pc),a0 ; access tens digit of year
subq.b #8,(a0) ; convert 1980 into 00
move.b (a0)+,(a2)+ ; move two year digits
move.b (a0)+,(a2)+
subq.l #6,a0 ; access month
move.b (a0)+,(a2)+ ; move two month digits
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+ ; move two day digits
move.b (a0)+,(a2)+
*
* --- convert the time string into binary nibbles
*
lea s_time(pc),a0 ; access time string
bsr conv2dig ; convert hours into binary
cmpi.b #'A',4(a0) ; is AM or PM indicated?
beq.s nnta ; branch if AM
cmpi.w #12,d0 ; is hour between 12:00 and 12:59?
beq.s nnta ; yes, then skip
addi.w #12,d0 ; adjust 1:00 into 13:00
nnta: divu #10,d0 ; split hours into digits
move.b d0,(a2)+ ; store tens digit of hours
swap d0 ; access ones digit
move.b d0,(a2)+ ; store ones digit of hours
move.b (a0)+,(a2)+ ; move two digits of minutes
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+ ; move two digits of seconds
move.b (a0)+,(a2)+
*
* --- translate ASCII digits into binary
*
moveq #13,d0 ; loop 14 bytes
xclr: andi.b #15,-(a2) ; convert ASCII digits to binary
dbra d0,xclr
*
* --- begin clock update
*
lea buffer+14(a5),a2 ; address end of time data
moveq #5,d0 ; command = stop clock
moveq #0,d1 ; address = 0
bsr w_clock ; write command to stop clock
moveq #1,d0 ; command = set 24 hour mode
moveq #30,d1 ; addr = 15
bsr w_clock ; write command
moveq #7,d0 ; command = interrupts off
moveq #0,d1 ; addr = 0
bsr w_clock ; write command
*
* --- reprogram all registers from the table and start clock
*
moveq #14,d3 ; loop for 15 writes
moveq #4,d1 ; begin addr = 2 (seconds register)
sb2c: move.b -(a2),d0 ; get next time digit
bsr w_clock ; change the time
dbra d3,sb2c
rts
* ==========================================================
* ===== conv2dig : convert decimal string into binary =====
* ==========================================================
*
* in: A0.L = address of string
* out: D0.L = binary value, range = 0..99
* A0.L = incremented by 2
* cc's : set by D0
* changed: D1
*
* This subroutine converts the two digit ASCII string pointed to by
* A0 into a binary value of the range 0..99. The alternate entry
* point 'tenx' forms D0.L = 10*D0 + D1
*
conv2dig:
moveq #15,d0 ; load mask for ten's digit
moveq #15,d1 ; load mask for one's digit
and.b (a0)+,d0 ; retrieve ten's digit
and.b (a0)+,d1 ; retrieve one's digit
*
* --- form the result: 10*D0 + D1
*
tenx: add.l d0,d0 ; 2x
add.l d0,d1 ; form 2x + y
add.l d0,d0 ; 4x
add.l d0,d0 ; 8x
add.l d1,d0 ; result = 8x + 2x + y = 10x + y
rts
* ========================================
* ===== chk_time : check time string =====
* ========================================
*
* in: none
* out: CC's : Z=1 if invalid string
* changed: a0,a1,d0,d1,d2
*
* This subroutine checks the time and date strings of the dialog for
* valid digits. If any invalid digit is present the condition codes
* are set accordingly before exit.
*
t_vld: dc.w $0003 ; month x 10 = [0..1]
dc.w $03ff ; month x 1 = [0..9]
dc.w $000f ; date x 10 = [0..3]
dc.w $03ff ; date x 1 = [0..9]
dc.w $0300 ; year x 10 = [8..9]
dc.w $03ff ; year x 1 = [0..9]
dc.w -1
dc.w $0003 ; hour x 10 = [0..1]
dc.w $03ff ; hour x 1 = [0..9]
dc.w $003f ; minute x 10 = [0..5]
dc.w $03ff ; minute x 1 = [0..9]
dc.w $003f ; second x 10 = [0..5]
dc.w $03ff ; second x 1 = [0..9]
*
chk_time:
lea s_date(pc),a0 ; address the date string
lea t_vld(pc),a1 ; point to table
moveq #11,d2 ; loop count = 6 + 6 digits
ct: moveq #15,d0 ; load mask
and.b (a0)+,d0 ; get lower nibble of digit
move.w (a1)+,d1 ; get validation bits
bpl.s cx ; branch unless validation = -1
lea s_time(pc),a0 ; if -1, switch to time string
bra.s ct ; and continue
cx: btst d0,d1 ; is digit valid?
dbeq d2,ct ; loop if valid, stop if not
rts ; return with cc's set
* ===================================
* ===== set_time : set the time =====
* ===================================
*
* in: none
* out: none
* changed:
*
* This routine checks the time and date strings of the dialog menu for
* validity. If the strings are valid the information in them is used
* to generate the bit formats necessary to tell GEM and TOS what the
* time and date are. Then the time and date are changed via system
* calls.
*
set_time:
bsr.s chk_time ; is the time and date valid?
beq.s stxit ; no, then exit
*
* --- convert date into BIOS format
*
lea s_date(pc),a0 ; address the date string
bsr.s conv2dig ; pull off the month
moveq #$0F,d7 ; load 4 bit mask
and.w d0,d7 ; 0000 0000 0000 mmmm
bsr.s conv2dig ; pull off the day of the month
andi.w #$001F,d0 ; mask down to 5 bits
lsl.w #5,d7 ; shift month bits left
or.w d0,d7 ; 0000 000m mmmd dddd
bsr conv2dig ; pull off the year
subi.w #80,d0 ; convert 80 into 00
andi.w #$007F,d0 ; mask down to 7 bits
ror.w #7,d0 ; roll year to high end of word
or.w d0,d7 ; yyyy yyym mmmd dddd
swap d7 ; save 'date' in high order bits of D7
*
* --- convert time into BIOS format
*
lea s_time(pc),a0 ; address time string
bsr conv2dig ; get HH
move.w d0,d7 ; 0000 0000 000h hhhh
bsr conv2dig ; get MM
cmpi.b #'A',(a0) ; are we AM or PM?
beq.s useAM ; branch if AM
cmpi.w #12,d7 ; are we 12:xx PM?
beq.s useAM ; yes, then don't correct
addi.w #12,d7 ; else convert 1..11 into 13..23
useAM: lsl.w #6,d7 ; shift bits to make room for minutes
andi.w #$003F,d0 ; mask minutes down to 6 bits
or.w d0,d7 ; 0000 0hhh hhmm mmmm
*
* --- align time and set seconds to zero
*
lsl.w #5,d7 ; hhhh hmmm mmm0 0000
*
* --- tell GEM what the date and time is
*
move.l d7,-(sp) ; pass [date:time] on stack
move.w #22,-(sp) ; function code
trap #14 ; tell GEM what date/time is
addq.l #6,sp ; fix stack
*
* --- tell TOS what the time is
*
move.w d7,-(sp) ; push "time"
move.w #45,-(sp) ; function code
trap #1 ; tell TOS what time is
addq.l #4,sp ; fix stack
*
* --- tell TOS what the date is
*
swap d7 ; reorder [date:time] to [time:date]
move.w d7,-(sp) ; push "date"
move.w #43,-(sp) ; function code
trap #1 ; tell TOS what date is
addq.l #4,sp ; fix stack
moveq #-1,d7 ; set condition codes to indicate OK
stxit: rts
* ==================================================
* ===== dialog : display dialog and await exit =====
* ==================================================
*
* in: A3.L = address of tree
* out: D3.W = object ID causing exit
* changed: A0, D0, ?
*
* This subroutine reserves memory, draws the tree addressed by A3,
* processes the dialog, erases the dialog, sets the button which caused
* exit to non-selected, and frees up the reserved memory. The object
* number of the button which caused exit is returned in D3.
*
dialog: bsr rsrv_win ; reserve window space
bsr treedraw ; draw the tree
bsr wfbutton ; wait for response
bra free_win ; erase window
* ==================================================
* ===== tstnclr : Test and Clear SELECTED bit =====
* ==================================================
*
* in: A3.L = tree address
* D3.W = object ID
* out: D3.W = incremented by 1
* D0.W = object's state word anded with 1
* cc's : set by D0.W
* changed: A0
*
* This subroutine tests the SELECTED bit of the object number passed in
* D3 and increments D3. The state of the bit is used to set a
* condition code before exit.
*
tstnclr:
bsr.s objba ; get address
moveq #SELECTED,d0 ; load mask
and.w (a0),d0 ; get bit
eor.w d0,(a0) ; clear bit if set
addq.w #1,d3 ; update
tst.w d0 ; set condition codes
rts
* ============================================
* ===== objba : object bit address ========
* ============================================
*
* input: A3.L = address of tree
* D3.W = object ID
* out: A0.L = address of object's state word
* changed: D0
*
* This subroutine is used to form the address of the resource object's
* STATE word when given the resource tree address and object number.
*
objba: move.w d3,d0 ; copy object number
mulu #24,d0 ; form 24 byte offset per object
lea 10(a3,d0.l),a0 ; STATE word is 10 bytes into object
rts
* ===========================================
* ===== objbset : object bit set ===========
* ===========================================
*
* in: A3.L = address of tree
* D3.W = object id
* D4.W = bit mask
* out: A0.L = address of object's state word
* changed: none
*
* This subroutine is used to 'OR' a bit mask with the STATE word of an
* object in a resource tree. The alternate entry point 'setsel' is
* used when the 'SELECTED' bit is to be set.
*
setsel: moveq #1,d4 ; load SELECTED bit mask
objbset: bsr.s objba ; form address
or.w d4,(a0) ; set bits by ORing
rts
* ==========================================
* ===== rsrv_win : reserve window ==========
* ==========================================
*
* in: A3.L = address of tree about to be displayed
* out: none
* changed: D0,D1,A0,A1
*
* This routine first calls the FORM_CENTER routine to set the x,y,w,h
* needed to center the window. Then control drops into FREE_WIN which
* reserves the memory needed for the window size
*
rsrv_win:
lea xx(a5),a1 ; addr temp area to receive x,y,w,h
bsr _form_ce ; calculate window center
moveq #0,d0 ; pass code for reserving space
bra.s fwep ; enter free_win routine
* =======================================================
* ===== free_win : free up memory reserved earlier =====
* =======================================================
*
* in: none
* out: none
* changed: D0,D1,A0,A1
*
* This subroutine frees up memory which was reserved earlier. The
* x,y,w,h clip rectangle was earlier stored at 'xx'.
*
free_win:
moveq #3,d0 ; use code = 3,
fwep: lea xx(a5),a0 ; load pointer to x,y,w,h area
bra.s _form_di ; free memory
* =====================================
* ===== objdraw : draw an object =====
* =====================================
*
* in: A3.L = address of tree
* D3.W = object to start with
* out: none
* changed: ?
*
* This subroutine draws the resource tree starting at the object number
* given in D3 and for 5 levels of offspring. The alternate entry point
* 'treedraw' starts at object number 0 for drawing an entire tree.
*
treedraw:
moveq #0,d3 ; for trees set object number to zero
objdraw:
lea xx(a5),a0 ; address x,y,w,h
moveq #5,d1 ; pass 5 levels
move.w d3,d0 ; pass object number in d0
bra _objc_dr ; draw
* ===============================================
* ===== wfbutton : wait for a button ===========
* ===============================================
*
* in: A3.L = tree address
* D0.W = object ID of editable text, 0 if none
* out: D3.W = ID of button causing exit
* changed: ?
*
* This routine calls the FORM_DO routine which processes the user
* interaction with a dialog. Upon exit the object number which was
* used to exit the dialog is returned in D3.
wfbutton:
moveq #0,d0 ; set object number to 0
wftext: bsr.s _form_do ; process dialog
move.w d0,d3 ; assign to exitobj
rts
* =================================
* ===== _APPL_IN : initialize =====
* =================================
*
* in: none
* out: D0.W = ap_id or -1 if error
* cc's : set by D0.W
* changed:
*
* This routine notifies GEM of an application and allows GEM to set up
* some housekeeping. An application ID is assigned and we store it
* in our global variable area.
*
_appl_in:
moveq #APPL_INI,d1 ; code = initialize
bsr.s gem_ep ; call GEM
move.w d0,ap_id(a5) ; store application ID
rts
* ===========================
* ===== _APPL_EX : exit =====
* ===========================
*
* in: none
* out: d0.w = 0 on error
*
* This routine notifies GEM of our intention to terminate.
*
_appl_ex:
moveq #APPL_EXI,d1 ; code = exit
bra.s gem_ep ; call GEM
* ===================================
* ===== _OBJC_DR : Object Draw =====
* ===================================
*
* in: d0.w = start obj
* d1.w = depth
* a0.l = address of x,y,w,h clip limits [4 words]
* a3.l = tree address
* out: d0.w = 0 if error occurred
*
_objc_dr:
lea int_in(a5),a1 ; address integer input array
move.w d0,(a1)+ ; store starting object
move.w d1,(a1)+ ; store drawing depth
move.l (a0)+,(a1)+ ; store x and y
move.l (a0)+,(a1)+ ; store w and h
move.l a3,addr_in(a5) ; store address of resource tree
moveq #OBJC_DRA,d1 ; set function code = object draw
bra.s gem_ep ; call GEM
* ======================================
* ===== _FORM_DO : Process Dialog =====
* ======================================
*
* in: d0.w = start object, a3.l = tree address
* out: d0.w = exit object
*
_form_do:
move.l a3,a0 ; pass tree address in A0
moveq #FORM_DO,d1 ; function = FORM DO
bra.s call_gem ; call GEM
* ==========================================
* ===== _FORM_DI : Dialog Housekeeping =====
* ==========================================
*
* in: d0.w = action [0=reserve, 1=grow, 2=shrink, 3=free]
* a0.l = address of x,y,w,h limits [4 words]
* out: d0.w = 0 if an error occurred
*
* This routine is used to reserve or release memory or to draw a
* growing or shrinking box. The operation code is passed in D0 and
* the second x,y,w,h dimensions are pointed to by a0. This routine
* is currently hard coded so that the first set of x,y,w,h points is
* always zero.
*
_form_di:
lea int_in(a5),a1 ; address integer input array
move.w d0,(a1)+ ; store operation code
clr.l (a1)+ ; x1 = 0, y1 = 0
clr.l (a1)+ ; w1 = 0, h1 = 0
move.l (a0)+,(a1)+ ; store x2, y2
move.l (a0)+,(a1)+ ; store w2, h2
moveq #FORM_DIA,d1 ; function = FORM_DIALOG
bra.s gem_ep ; call GEM
* ===========================================
* ===== _FORM_AL : Process Alert Boxes =====
* ===========================================
*
* in: d0.w = default exit button, a0 = alert string address
* out: d0.w = exit button used, 1=first, 2=second, etc.
*
* This routine displays and processes user interaction with the alert
* box. The address of the alert string is passed in A0 and the default
* exit button if more than one is present is passed in D0. The
* alternate entry point '_alert' sets the default exit button to 1.
*
_alert: moveq #1,d0 ; default exit button = 1 (leftmost)
_form_al:
moveq #FORM_ALE,d1 ; function code
bra.s call_gem ; call GEM
* ==============================================
* ===== _FORM_CE : Calculate box centering =====
* ==============================================
*
* in: a3.l = address of tree
* a1.l = addr of area to store x,y,w,h of centered tree
* out: none
*
* This routine calculates the x and y coordinates necessary to center
* the resource treee addressed by A3 on the screen. The x,y,w,h
* coordinates necessary for a clip rectangle are returned and stored
* at the address passed in A1.
*
_form_ce:
move.l a3,a0 ; pass tree address in A0
moveq #FORM_CEN,d1 ; function = form center
bsr.s call_gem ; call gem
lea int_out+2(a5),a0 ; access x,y,w,h returned
move.l (a0)+,(a1)+ ; store x,y
move.l (a0)+,(a1)+ ; store w,h
rts
* ========================================
* ===== _GRAF_MO : Change Mouse Form =====
* ========================================
*
* in: d0.w = code of mouse form desired
* out: d0.w = 0 if error
* changed:
*
* This routine changes the form of the mouse pointer used. It can also
* be used to hide and unhide the mouse.
*
_mouse: moveq #0,d0 set mouse form to pointer
_graf_mo:
suba.l a0,a0
moveq #GRAF_MOU,d1
* =======================================================
* ===== call_gem : set up parameters for a gem call =====
* =======================================================
*
* in: D1.W = op code number
* D0.W = optional int_in[0]
* A0.L = optional addr_in[0]
* out: D0.W = returned value from int_out[0], if any
* changed: A0,A1,D1
*
* This subroutine uses the op code number passed in D1 to
* look up the number of integers and addresses in and out for the
* GEM call. This information is then stored in the 'CONTROL' array
* located in the dynamic storage area. Then GEM call is then
* performed and a possible return code is loaded into D0 before exit.
*
call_gem:
move.l a0,addr_in(a5) in case there's an address in
move.w d0,int_in(a5) in case there's an integer in
gem_ep: movem.l d2-d7/a1-a6,-(sp) ; save registers
add.w d1,d1 ; function x 2
add.w d1,d1 ; function x 4
lea gemtbl(pc,d1.w),a0 ; form address of entry
*
* --- transfer opcode, integers in, integers out, and addresses
*
lea control(a5),a1 ; address control array
moveq #0,d0 ; form a zero
movep.l d0,0(a1) ; clear upper bytes of control[0..3]
move.l (a0),d0 ; get bytes from table entry
movep.l d0,1(a1) ; fill lower bytes of control[0..3]
clr.w 8(a1) ; set control[4] to zero
*
* --- perform the GEM/AES call
*
move.l a5,d1 ; pass address of 'control' array in D1
move.w #200,d0 ; pass special function number in D0
trap #2 ; call the system
movem.l (sp)+,d2-d7/a1-a6 ; restore registers
moveq #0,d0 ; clear upper portion of register
move.w int_out(a5),d0 ; retrieve a return value
rts
*
* --- Table of control parameters for AES calls
*
* each entry has: AES/GEM function number
* number of integers (words) in
* number of integers (words) out
* number of address (longs) in
*
gemtbl: dc.b 10,0,1,0 ; APPL_INIT
dc.b 19,0,1,0 ; APPL_EXIT
dc.b 42,6,1,1 ; OBJC_DRAW
dc.b 50,1,1,1 ; FORM_DO
dc.b 51,9,1,0 ; FORM_DIAL
dc.b 52,1,1,1 ; FORM_ALERT
dc.b 54,0,5,1 ; FORM_CENTER
dc.b 78,1,1,1 ; GRAF_MOUSE
*
* --- strings for alerts
*
warning: dc.b '[3][ Clock missing or | not working ][ OK ]',0
badtime: dc.b '[3][Bad Time or Date,|please retry][ OK ]',0
*
* --- strings for dialog
*
null: dc.b 0
s_time: dc.b '122345A',0
s1: dc.b 'TIME = __:__:__ _M',0
s2: dc.b '999999F',0
s_date: dc.b '071486',0
s4: dc.b 'DATE = __/__/__',0
s5: dc.b '999999',0
s6: dc.b 'SUN',0
s7: dc.b 'MON',0
s8: dc.b 'TUE',0
s9: dc.b 'WED',0
s10: dc.b 'THU',0
s11: dc.b 'FRI',0
s12: dc.b 'SAT',0
s13: dc.b 'SET',0
s14: dc.b 'EXIT',0
s15: dc.b 'CLOCK CARTRIDGE',0
*
* ========== text info structures ========== *
*
* each entry: L - pointer to text
* L - pointer to template
* L - pointer to validation string
* W - font to be used, 3=normal, 5=small
* W - 6
* W - justification (left, center, right)
* W - color code
* W - 0
* W - border thickness ( + outward, - inward )
* W - length of text (including null)
* W - length of template (including null)
* =====
* 28 bytes
*
*
* --- text info blocks
*
ti0: dc.l s_time,s1,s2 ; time
dc.w 3,6,0,$1180
dc.w 0,-1,8,19
ti1: dc.l s_date,s4,s5 ; date
dc.w 3,6,0,$1180
dc.w 0,-1,7,16
ti2: dc.l s15,null,null ; title string
dc.w 3,6,2,$1180
dc.w 0,-3,16,1
*
* ========== object structures ========== *
*
* each entry: W - ID of next sibling (-1 if none)
* W - ID of first offspring (-1 if none)
* W - ID of last offspring (-1 if none)
* W - type of object
* W - object flags
* W - state flags (selected, open, etc)
* L - <expansion>
* W - x position of upper left corner (relative to parent)
* W - y position of upper left corner
* W - width in pixels
* W - height in pixels
* =====
* 24 bytes
*
* --- object types:
*
BOX EQU 20 ; box
TXT EQU 21 ; text
BOXTEXT EQU 22 ; text within a box
IMAGE EQU 23 ; bit image
PROGDEF EQU 24 ; programmer defined
IBOX EQU 25 ; invisible box
BUTTON EQU 26 ; text within a button
BOXCHAR EQU 27 ; single char within a button
STRING EQU 28 ; string
ETEXT EQU 29 ; editable text
EBOXTEXT EQU 30 ; editable text within a box
ICON EQU 31 ; icon image
TITLE EQU 32 ; string used in menu titles
*
* --- object option flags:
*
NONE EQU $0000 ; no option
SLECTBLE EQU $0001 ; SLECTBLE
DEFAULT EQU $0002 ; default for <CR>
EXIT EQU $0004 ; causes exit when selected
EDITABLE EQU $0008 ; editable text
RADIOB EQU $0010 ; radio button
LASTOB EQU $0020 ; last object in tree
*
* --- object states:
*
NORMAL EQU $0000 ; nothing special
SELECTED EQU $0001 ; has been selected by the mouse button
DISABLED EQU $0008 ; can't be selected
OUTLINED EQU $0010 ; shows up as outlined
SHADOWED EQU $0020 ; shows up as casting a shadow
*
* ===== RESOURCE TREE: ================================================
*
tree: dc.w -1,01,01,BOX ; outermost box
dc.w NONE,NORMAL
dc.l $00011100
dc.w 0,0,262,174
* obj 1
dc.w 00,02,14,BOX
dc.w SLECTBLE+EXIT,NORMAL ; inner framing box
dc.l $00FD1103
dc.w 7,7,248,160
* obj 2
dc.w 03,-1,-1,ETEXT ; editable date string
dc.w EDITABLE,NORMAL
dc.l ti1
dc.w 79,55,120,16
* obj 3
dc.w 04,-1,-1,ETEXT ; editable time string
dc.w EDITABLE,NORMAL
dc.l ti0
dc.w 79,78,144,16
* obj 4
dc.w 12,05,11,BOX ; box surrounding radio buttons
dc.w NONE,NORMAL
dc.l $00FF1100
dc.w 16,16,43,126
* obj 5
dc.w 06,-1,-1,BUTTON ; radio button for SUN
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s6
dc.w 1,1,41,16
* obj 6
dc.w 07,-1,-1,BUTTON ; MON
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s7
dc.w 1,19,41,16
* obj 7
dc.w 08,-1,-1,BUTTON ; TUE
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s8
dc.w 1,37,41,16
* obj 8
dc.w 09,-1,-1,BUTTON ; WED
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s9
dc.w 1,55,41,16
* obj 9
dc.w 10,-1,-1,BUTTON ; THU
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s10
dc.w 1,73,41,16
* obj 10
dc.w 11,-1,-1,BUTTON ; FRI
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s11
dc.w 1,91,41,16
* obj 11
dc.w 04,-1,-1,BUTTON ; SAT
dc.w (RADIOB+SLECTBLE),NORMAL
dc.l s12
dc.w 1,109,41,16
* obj 12
dc.w 13,-1,-1,BUTTON ; 'SET' button
dc.w 5,SHADOWED
dc.l s13
dc.w 72,112,64,16
* obj 13
dc.w 14,-1,-1,BUTTON ; 'EXIT' button
dc.w 5,SHADOWED
dc.l s14
dc.w 160,112,64,16
* obj 14
dc.w 01,-1,-1,BOXTEXT ; title in a box
dc.w LASTOB+SLECTBLE+EXIT,NORMAL
dc.l ti2
dc.w 80,16,136,16
*
* --- dynamic storage area begins at end of program
*
* The dynamic storage is an uninitialized temporary data area that
* begins at the end of the program. It is used for the stack and all
* variables that do not need to be initialized prior to program
* execution. Use of a dynamic storage area reduces the disk space
* requirements of the program.
*
storage: nop
end